

local role_getlogic = function()
  local role_logic = GameLogic:subclass("hx__role_logic")

  function role_logic:initialize(room)
    GameLogic.initialize(self, room)
    self.role_table = {
      { "lord" },
      { "lord", "rebel" },
      { "lord", "rebel", "renegade" },
      { "lord", "loyalist", "rebel", "renegade" },
      { "lord", "loyalist", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "rebel", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "loyalist", "rebel", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "loyalist", "rebel", "rebel", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "loyalist", "loyalist", "rebel", "rebel", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "loyalist", "loyalist", "rebel", "rebel", "rebel", "rebel", "renegade", "renegade" },
    }
  end

  function role_logic:assignRoles()
    local room = self.room
    local n = #room.players
    local roles = self.role_table[n]
    table.shuffle(roles)

    for i = 1, n do
      local p = room.players[i]
      p.role = roles[i]
      if p.role == "lord" then
        room:setPlayerProperty(p, "role_shown", true)
      end
      room:broadcastProperty(p, "role")
    end

    local function getPlayerByScreenName(Room, name)
      return table.find(Room.players, function(p)
        return p._splayer:getScreenName() == name
      end)
    end

    local croom = room.room
    local cowner = croom:getOwner()
    local owner = getPlayerByScreenName(room, cowner:getScreenName())
    local choices = {}
    local generalNum = room.settings.generalNum
    for i = 1, generalNum * 2 do
      choices[i] = tostring(i)
    end
    table.insert(choices, 1, "0")
    local changenum = room:askToChoice(owner, {
      choices = choices,
      skill_name = "game_rule",
      prompt = "#hx__choose_changenum",
      cancelable = false,
    })
    local num = tonumber(changenum) or 0
    room:setBanner("changeGeneralNum", num)
    room:sendLog{ type = "#hx__changenum_tips", arg = num, toast = true }

  end

  --- 分配座位
  function role_logic:adjustSeats()
    local player_circle = {}
    local players = self.room.players
    local p = 1
    for i = 1, #players do
      if players[i].role == "lord" then
        p = i
        break
      end
    end
    for j = p, #players do
      table.insert(player_circle, players[j])
    end
    for j = 1, p - 1 do
      table.insert(player_circle, players[j])
    end

    self.room:arrangeSeats(player_circle)
  end

  -- function role_logic:prepareDrawPile()
  --   local room = self.room
  --   local allCardIds = Fk:getAllCardIds()
  --   local filterCardIds = {}
  --   --卡牌白名单
  --   local white_cards = {"standard","standard_cards","maneuvering","tenyear_token","mobile_derived","ol_token","overseas_token","th_jie_fuzhi1_cards","th_jie_fuzhi2_cards","th_jie_fuzhi3_cards"}
  --   for i = #allCardIds, 1, -1 do
  --     local id = allCardIds[i]
  --     local card = Fk:getCardById(id)
  --     if card then
  --       if card.is_derived or not table.contains(white_cards, card.package.name) then
  --         table.removeOne(allCardIds, id)
  --         table.insert(room.void, id)
  --         room:setCardArea(id, Card.Void, nil)
  --       end
  --       if table.contains(white_cards, card.package.name) then
  --         if not card.is_derived then
  --           table.insert(filterCardIds, id)
  --         end
  --       end
  --     end
  --   end
  --   local seed = math.random(2 << 32 - 1)
  --   table.shuffle(filterCardIds, seed)
  --   room.draw_pile = filterCardIds
  --   for _, id in ipairs(room.draw_pile) do
  --     room:setCardArea(id, Card.DrawPile, nil)
  --   end
  --   room:doBroadcastNotify("PrepareDrawPile", seed)
  -- end

  function role_logic:chooseGenerals()
    local room = self.room ---@class Room


    local targets = table.filter(room.players, function(p) return p.id > 0 end)
    local choices = {"0","1","2","3","4","5","6","7","8","9","10"}
    local result = room:askToJointChoice(room.players[1], {
      choices = choices,
      players = targets,
      prompt = "#hx_role-generalnum",
    })
    local refreshgeneral = 0
    for _, p in ipairs(targets) do
      refreshgeneral = refreshgeneral + tonumber(result[p])
    end
    if refreshgeneral >= #targets then
      refreshgeneral = math.floor(refreshgeneral / #targets)
      room:doBroadcastNotify("ShowToast", "本局可多选"..refreshgeneral.."个武将")
    else
      refreshgeneral = 0
      room:doBroadcastNotify("ShowToast", "本局多选将未开启")
    end

    local generalNum = room.settings.generalNum
    if refreshgeneral > 0 then
      generalNum = generalNum + refreshgeneral
    end
    local n = room.settings.enableDeputy and 2 or 1
    local lord = room:getLord()
    local lord_generals = {}
    local lord_num = 3
    -- local white_generals = {
    --   "huixiangqy__liuchen","huixiangqy__spzhouyu","huixiangqy__jieluotong","huixiangqy__xingsunquan","huixiangqy__daoxusheng","huixiangqy__spsimayi","huixiangqy__jiequyi","huixiangqy__bianzhouchu","huixiangqy__shenxusheng",
    --   "evol__agulV2","evol__gaiaV1","evol__zepdon","evol__sporb","evol__orb3","evol__orbpheti","evol__dijia","ulti__phoenixA","ulti__J0529_4351","ulti__xeagr","diy_qun__shuhuxiangli","diy_qun__wuhuxiangli","diy_qun__hundunhuxiangli",
    --   "diy_qun__menghuxiangli","diy_qun__huxiangli","abst__machao","abst__nailong","abst__kebi","abst__xusheng","abst__sunxiaochuan","origin__dongfangbubai","origin__haimian","origin__gbwang","origin__gytz","origin__pilaoban","fsb__jiangziya",
    --   "girlth__shixin","girlth__shaonv6","regrets__sanli","regrets__wulvmeng","DIEND","sy__lvbu","hxyiwu__yanjun","hxqunyou__chgs","hxqunyouji__miheng","hxqunyou__qiamimiao","hxqunyou__songxingnu","hxqunyou__wuming","hxqunyou__ytys",
    --   "hxqunyou__genie","hxqunyou__limulu","hxqunyou__ronghuanggai","hxqunyou__nijvshou","hxqunyou__muzhugeliang","hxqunyou__xingsunce","hxqunyou__T800","hxqunyou__hechunqiu","hxqunyou__guyuefangyuan","hxqunyou__suxiao","hxqunyou__zhugejing", 
    --   "hxqunyou__shendengai","hxqunyoumou__guohuai","hxqunyoumou__huoqubing","hxqunyoumou__jvshou","hxqunyou__yujin","hxqunyou__wuzuge","hxqunyou__godsunquan","hxqunyou__baigou","hxxishi__yaomeng","hxxishi__huangjinfashi",
    --   "hxjsctB__godpeixiu","hxjsct__guinv","hxjsctB__dabai","hxjsct__fkyshr", "hxjsct__ruifeng","hxjsct__yanchixia","hxjsct__kakaluote", "hxjsct__xzc_gj","hxjsct__jianshenwuming","hxjsctB__simazhao","hxjsct__blackrx","hxjsct__donghuangtaiyi",
    --   "qshm__godzhangjiao","qyt__godcaocao","qyt__godsimayi","qyt__dianwei","qyt__dengai","shzj_yiling__luxun","anying","shzj_guansuo__lvmeng","shzj_guansuo__guansuo", "godguanyu","gundam","longwang","sunwukong","nezha","wuming", "godhuangzhong",
    --   "godpangtong","zhangwei","os__xia__guanyu","os__dongzhao","os__xunchen","huchuquan","os__haomeng","simafu","zhangzhao","os_mou__caopi","ofl__xiahouxuan","ofl__guozhao","ofl__zhonghui","ofl__godzhangjiao","godhuangfusong","ofl__gaowang","yongkai",
    --   "quexiaojiang","ofl__godjiaxu", "ofl__godcaocao","ofl__fanchou","ofl2__caopi","ofl__wolong","ofl2__godmachao","ofl__godjiangwei",  "LoR_luolan","LoR_kali","LoR__angel_master","LoR__angel_fire","LoR__angel_yuanchu","LoR__Tiphereth",
    --   "LoR__milisi","LoR__Shao","LoR__Shidifen","LoR__Binah",  "Qunyou_Rem","Qunyou_biyanluo_jueti","Qunyou_ying_uuz","Qunyou_junshen","Qunyou_Gui_Rem","Qunyou_changgeng","Qunyou_shaniu","Qunyou_wukong","Qunyou_rulai", "Qunyou_huda4","Qunyou_yudi",
    --   "Qunyou_chusheng","Qunyou_suomi1973","Qunyou_wenyang","Qunyou_jie_sp_zhaoyun","Qunyou_yuzhiboguang","Qunyou_zhichenshu","Qunyou_keluonuosi","Qunyou_jieruo","Qunyou_682", "Qunyou_liyue","Qunyou_yanxi","Qunyou_gulang","Qunyou_zhujiecangxing",
    --   "Qunyou_baisuzhen","Qunyou_modi",
    -- }
    --黑名单武将
    local black_generals = {
      -- "evol__saga","evol__youtong","evol__legend","evol__endora","evol__Delacion","evol__cosmos3","diy_qun__huyanmin", "Qunyou_biyanluo",
      -- "Qunyou_yasina","Qunyou_DR","Qunyou_weihuacun","Qunyou_jingjiexianzhe", "ulti__jiehai","ulti__gagtua","ulti__LHZetton",
    }
    --白名单武将
    local white_generals = table.filter(room.general_pile, function(g)
      return not table.contains(black_generals, g)
    end)


    if lord ~= nil then
      room:setCurrent(lord)
      local a1 = #room.general_pile
      local a2 = #room.players * generalNum
      if a1 < a2 then
        room:sendLog{
          type = "#NoEnoughGeneralDraw",
          arg = a1,
          arg2 = a2,
          toast = true,
        }
        room:gameOver("")
      end
      lord_num = math.min(a1 - a2, lord_num)
      local generals = table.connect(room:findGenerals(function(g)
        return not table.contains(black_generals, g)
      end, lord_num), table.random(white_generals, generalNum * #room.players))

      --获取可换的武将
      local function getChange(all_cards, can_change, id)
        local seat = room:getPlayerById(id).seat
        local change = {}
        if seat == 1 then
          change = table.slice(all_cards, 1, can_change + 1)
        else
          change = table.slice(all_cards,can_change * (seat - 1) + 1, can_change * seat + 1)
        end
        return change
      end

      local can_change = room:getBanner("changeGeneralNum") or 0 --换将次数
      local all_cards = table.map(Fk:getGeneralsRandomly( (can_change * #room.players) + lord_num, Fk:getAllGenerals(), generals), Util.NameMapper)
      table.shuffle(all_cards)

      local data_table_true = {}
      for _, p in ipairs(room.players) do
        local arg = getChange(generals, generalNum, p.id)
        if p.role == "lord" then  ----主公多发3个武将
          local count = #all_cards
          arg[#arg+ 1] = all_cards[count]
          arg[#arg + 1] = all_cards[count - 1]
          arg[#arg + 1] = all_cards[count - 2]
        end
        data_table_true[p.id] = {
          change = getChange(all_cards, can_change, p.id),
          cards = arg,  --generals
          num = n,  --n
          no_c = false, --no_convert
          heg = false, --heg
          type = "askForGeneralsChosen", --rule
          extra = {n = n}, --extra_data
        }
      end
      room:askToMiniGame({lord}, {
        skill_name = "AskForGeneral",
        game_type = "ChooseGeneralWithCanChange",
        data_table = {
          [lord.id] = data_table_true[lord.id],
        },
        timeout = self.room.settings.generalTimeout,
      })

      -- lord_generals = room:askToChooseGeneral(lord, { generals = generals, n = n })
      -- local lord_general, deputy
      -- if type(lord_generals) == "table" then
      --   deputy = lord_generals[2]
      --   lord_general = lord_generals[1]
      -- else
      --   lord_general = lord_generals
      --   lord_generals = {lord_general}
      -- end
      -- generals = table.filter(generals, function(g)
      --   return not table.find(lord_generals, function(lg)
      --     return Fk.generals[lg].trueName == Fk.generals[g].trueName
      --   end)
      -- end)
      -- room:returnToGeneralPile(generals)
      local lord_result = lord.client_reply
      local lord_general = lord_result[1]
      local lord_deputy = lord_result[2]
      room:prepareGeneral(lord, lord_general, lord_deputy, true)

      room:askToChooseKingdom({lord})
      room:broadcastProperty(lord, "kingdom")

      -- 显示技能
      local canAttachSkill = function(player, skillName)
        local skill = Fk.skills[skillName]
        if not skill then
          fk.qCritical("Skill: "..skillName.." doesn't exist!")
          return false
        end
        if skill:hasTag(Skill.Lord) and not (player.role == "lord" and player.role_shown and room:isGameMode("hx__role_mode")) then
          return false
        end

        if skill:hasTag(Skill.AttachedKingdom) and not table.contains(skill:getSkeleton().attached_kingdom, player.kingdom) then
          return false
        end

        return true
      end

      local lord_skills = {}
      for _, s in ipairs(Fk.generals[lord.general].skills) do
        if canAttachSkill(lord, s.name) then
          table.insertIfNeed(lord_skills, s.name)
        end
      end
      for _, sname in ipairs(Fk.generals[lord.general].other_skills) do
        if canAttachSkill(lord, sname) then
          table.insertIfNeed(lord_skills, sname)
        end
      end

      local deputyGeneral = Fk.generals[lord.deputyGeneral]
      if deputyGeneral then
        for _, s in ipairs(deputyGeneral.skills) do
          if canAttachSkill(lord, s.name) then
            table.insertIfNeed(lord_skills, s.name)
          end
        end
        for _, sname in ipairs(deputyGeneral.other_skills) do
          if canAttachSkill(lord, sname) then
            table.insertIfNeed(lord_skills, sname)
          end
        end
      end
      for _, skill in ipairs(lord_skills) do
        room:doBroadcastNotify("AddSkill", {
          lord.id,
          skill
        })
      end

      local nonlord = room:getOtherPlayers(lord, true)
      -- local req = Request:new(nonlord, "AskForGeneral")
      -- local allgenerals = table.filter(room.general_pile, function(g)
      --   return not table.contains(black_generals, g)
      -- end)
      -- local generals = table.random(allgenerals, #nonlord * generalNum)
      -- for i, p in ipairs(nonlord) do
      --   local arg = table.slice(generals, (i - 1) * generalNum + 1, i * generalNum + 1)
      --   req:setData(p, { arg, n })
      --   req:setDefaultReply(p, table.random(arg, n))
      -- end

      -- for _, p in ipairs(nonlord) do
      --   local result = req:getResult(p)
      --   local general, deputy = result[1], result[2]
      --   room:findGeneral(general)
      --   room:findGeneral(deputy)
      --   room:prepareGeneral(p, general, deputy)
      -- end

      room:askToMiniGame(nonlord, {
        skill_name = "AskForGeneral",
        game_type = "ChooseGeneralWithCanChange",
        data_table = data_table_true,
        timeout = self.room.settings.generalTimeout,
      })

      for _, p in ipairs(nonlord) do
        local p_result = p.client_reply
        local general = p_result[1]
        local deputy = p_result[2]
        room:prepareGeneral(p, general, deputy)
      end

      room:askToChooseKingdom(nonlord)

      for _, p in ipairs(nonlord) do
        room:broadcastProperty(p, "general")
        room:broadcastProperty(p, "deputyGeneral")
      end
    end
  end

  return role_logic
end

local role_mode = fk.CreateGameMode{
  name = "hx__role_mode",
  minPlayer = 2,
  maxPlayer = 10,
  logic = role_getlogic,
  main_mode = "role_mode",
  is_counted = function(self, room)
    return #room.players >= 5
  end,
  build_draw_pile = function(self)
    local allCardIds = Fk:getAllCardIds()
    local filterCardIds = {}
    local void = {}
    --卡牌白名单
    local white_cards = {"standard","standard_cards","maneuvering","tenyear_token","mobile_derived","ol_token","overseas_token"}
    for i = #allCardIds, 1, -1 do
      local id = allCardIds[i]
      local card = Fk:getCardById(id)
      if card then
        if card.is_derived or not table.contains(white_cards, card.package.name) then
          table.removeOne(allCardIds, id)
          table.insert(void, id)
        end
        if table.contains(white_cards, card.package.name) then
          if not card.is_derived then
            table.insert(filterCardIds, id)
          end
        end
      end
    end
    return filterCardIds, void
  end,
  surrender_func = function(self, playedTime)
    local roleCheck = false
    local roleText = ""
    local alive_players = table.filter(Fk:currentRoom().players, function(p)
      return not p.dead or p.rest > 0
    end)
    if Self.role == "renegade" then
      roleCheck = not table.find(alive_players, function(p)
        return p ~= Self and table.contains({"rebel", "rebel_chief", "renegade"}, p.role)
      end)
      roleText = "left lord and loyalist alive"
    elseif Self.role == "rebel" or Self.role == "rebel_chief" then
      roleCheck = #table.filter(alive_players, function(p)
        return table.contains({"rebel", "rebel_chief"}, p.role)
      end) == 1
      roleText = "left one rebel alive"
    else
      if Self.role == "loyalist" or Self.role == "civilian" then
        return { { text = Self.role.." never surrender", passed = false } }
      else
        if #alive_players < 3 then
          roleCheck = true
        else
          roleText = "left you alive"
          local left_loyalist, left_rebel, left_renegade = false, false, false
          for _, p in ipairs(alive_players) do
            if p ~= Self then
              if table.contains({"lord", "loyalist"}, p.role) then
                left_loyalist = true
                break
              else
                if table.contains({"rebel", "rebel_chief"}, p.role) then
                  left_rebel = true
                elseif p.role == "renegade" then
                  left_renegade = true
                end
              end
            end
          end
          if left_loyalist then
            roleCheck = false
          else
            roleCheck = not (left_rebel and left_renegade)
          end
        end
      end
    end

    return {
      { text = "time limitation: 2 min", passed = playedTime >= 120 },
      { text = roleText, passed = roleCheck },
    }
  end,
}

Fk:loadTranslationTable{
  ["time limitation: 2 min"] = "游戏时长达到2分钟",
  ["#hx_role-generalnum"] = "请选择可多选的武将数，将取所有非人机玩家选项的平均值（向下取整）",
  ["hx__role_mode"] = "多选身份",
  [":hx__role_mode"] = [========================================[
# 多选身份模式简介

其实就是至多10人的身份模式，同时加入了另类换将卡与真换将卡。身份分配参考下表：


| 玩家人数 | 主公 | 忠臣 | 反贼 | 内奸 |
| -------- | ---- | ---- | ---- | ---- |
| 2        | 1    | 0    | 1    | 0    |
| 3        | 1    | 0    | 1    | 1    |
| 4        | 1    | 1    | 1    | 1    |
| 5        | 1    | 1    | 2    | 1    |
| 6        | 1    | 1    | 3    | 1    |
| 7        | 1    | 2    | 3    | 1    |
| 8        | 1    | 2    | 4    | 1    |
| 9        | 1    | 3    | 4    | 1    |
| 10        | 1    | 3    | 4    | 2    |



  ]========================================],
}



return role_mode
